package service

import (
	"JK-Junior-Go-Engineer-Camp/webook/internal/domain"
	"JK-Junior-Go-Engineer-Camp/webook/internal/repository"
	"JK-Junior-Go-Engineer-Camp/webook/pkg/logger"
	"context"
	"errors"
)

type ArticleService interface {
	// Save 帖子的保存和修改
	Save(ctx context.Context, art domain.Article) (int64, error)
	// Publish 帖子的发布
	Publish(ctx context.Context, art domain.Article) (int64, error)
}

type articleService struct {
	repo repository.ArticleRepository
	// V1 写法，演示:
	readerRepo repository.ArticleReaderRepository
	authorRepo repository.ArticleAuthorRepository
	l          logger.LoggerV1
}

func NewArticleService(repo repository.ArticleRepository) ArticleService {
	return &articleService{repo: repo}
}

// NewArticleServiceV1 V1版本演示：在Service层划分
func NewArticleServiceV1(
	readerRepo repository.ArticleReaderRepository,
	authorRepo repository.ArticleAuthorRepository,
	l logger.LoggerV1) *articleService {
	return &articleService{
		readerRepo: readerRepo,
		authorRepo: authorRepo,
		l:          l,
	}
}

func (a *articleService) Save(ctx context.Context, art domain.Article) (int64, error) {
	if art.Id > 0 {
		err := a.repo.Update(ctx, art)
		return art.Id, err
	}
	return a.repo.Create(ctx, art)
}

func (a *articleService) Publish(ctx context.Context, art domain.Article) (int64, error) {
	return a.repo.Sync(ctx, art)
}

func (a *articleService) PublishV1(ctx context.Context, art domain.Article) (int64, error) {
	var (
		id  = art.Id
		err error
	)
	// 操作制作库
	if id > 0 {
		err = a.authorRepo.Update(ctx, art)
	} else {
		id, err = a.authorRepo.Create(ctx, art)
	}
	if err != nil {
		return 0, err
	}
	// 操作线上库
	art.Id = id              // 保持线上库和制作库的ID一致
	for i := 0; i < 3; i++ { // 重试3次
		err = a.readerRepo.Save(ctx, art)
		if err != nil {
			a.l.Error("保存到制作库成功，到线上库失败",
				logger.Int64("aid", id), logger.Error(err))
			// TODO:可以在这里进一步接入metrics或者tracing之后，进一步记录必要的DEBUG信息
		} else {
			return id, nil
		}
	}
	a.l.Error("保存到制作库成功，到线上库失败，重试次数耗尽",
		logger.Int64("aid", id), logger.Error(err))
	return id, errors.New("保存到线上库失败，重试次数耗尽")
}
